SPB Git forge
15commits 1branches 0releases
29.7 MBsize
maindefault branch
10 days agolast push
TypeScript 36.3% Python 31.8% Go 18% JavaScript 9.8% Shell 1.9% SQL 1.4% CSS 0.5%
6.0 KB · 120 lines tsx
Raw Blame History
1import type { Metadata } from 'next';2import Link from 'next/link';3import { ScopeHeader } from '@/components/detail/ScopeHeader';4import { ScopePressureChart } from '@/components/detail/ScopeCharts';5import { TargetsTable } from '@/components/detail/Tables';6import { IncidentsSection } from '@/components/incidents/IncidentsSection';7import { ProbeTargetMatrix } from '@/components/service/ProbeTargetMatrix';8import { VendorIndicator } from '@/components/service/VendorIndicator';9import { Section, Stat } from '@/components/ui/primitives';10import { apiGet, apiTry } from '@/lib/api';11import { fmt, fmtInt, fmtMs, fmtPct } from '@/lib/format';12import { Time } from '@/lib/time';13import type { ServiceDetail } from '@/lib/types';1415export const dynamic = 'force-dynamic';1617type Params = Promise<{ slug: string }>;1819export async function generateMetadata({ params }: { params: Params }): Promise<Metadata> {20  const { slug } = await params;21  const s = await apiTry<ServiceDetail>(`/api/v1/service/${encodeURIComponent(slug)}`);22  if (!s) return { title: 'Service' };23  return { title: `${s.name} — observed pressure ${fmt(s.pressure)}, availability ${fmtPct(s.observed.availability_24h, 2)}`, description: s.discrepancy ?? `Independent observation of ${s.name} from our probe network versus the vendor status page.`, alternates: { canonical: `/service/${s.slug}` } };24}2526export default async function ServicePage({ params }: { params: Params }) {27  const { slug } = await params;28  const s = await apiGet<ServiceDetail>(`/api/v1/service/${encodeURIComponent(slug)}`);29  const ttfbShift = s.observed.ttfb_ms_median_1h - s.observed.ttfb_ms_baseline;30  return (31    <div className="pb-8">32      <ScopeHeader kicker={`Service · ${s.category}`} title={s.name} subtitle={<>{fmtInt(s.targets.length)} endpoints measured from every probe · observed availability 24 h {fmtPct(s.observed.availability_24h, 2)}</>} pressure={s.pressure} level={s.level} />3334      {s.discrepancy && (35        <div role="note" className="mb-4 border-l-2 border-warn bg-[rgba(233,196,106,0.06)] px-4 py-3 text-[13px]">36          <p className="label mb-1 text-warn">Discrepancy</p>37          <p className="text-ink">{s.discrepancy}</p>38        </div>39      )}4041      <div className="grid grid-cols-[minmax(0,1fr)] gap-x-10 md:grid-cols-2">42        <Section label="Observed by InternetPressure" className="min-w-0">43          <div className="grid grid-cols-2 gap-x-4 gap-y-4 sm:grid-cols-3">44            <Stat label="availability 1h" value={<span style={{ color: s.observed.availability_1h < 0.99 ? 'var(--p-high)' : undefined }}>{fmtPct(s.observed.availability_1h, 2)}</span>} />45            <Stat label="availability 24h" value={fmtPct(s.observed.availability_24h, 2)} />46            <Stat label="failures 1h" value={<span style={{ color: s.observed.failures_1h > 5 ? 'var(--p-elevated)' : undefined }}>{fmtInt(s.observed.failures_1h)}</span>} />47            <Stat label="TTFB p50 1h" value={fmtMs(s.observed.ttfb_ms_median_1h)} sub={`baseline ${fmtMs(s.observed.ttfb_ms_baseline)} · ${ttfbShift >= 0 ? '+' : ''}${fmt(ttfbShift, 0)} ms`} />48            <Stat label="TLS p50 1h" value={fmtMs(s.observed.tls_ms_median_1h, 1)} />49            <Stat label="pressure" value={<span style={{ color: `var(--p-${s.level})` }}>{fmt(s.pressure)}</span>} />50          </div>51        </Section>52        <Section label="Vendor status page" className="min-w-0">53          {s.vendor_status ? (54            <div className="space-y-2 text-[13px]">55              <div className="flex items-center justify-between">56                <VendorIndicator v={s.vendor_status} />57                <span className="num text-[11px] text-ink-3">58                  checked <Time ts={s.vendor_status.checked_at} style="time" />59                </span>60              </div>61              <p className="text-ink-2">62                {s.vendor_status.incidents ? `${s.vendor_status.incidents} incident${s.vendor_status.incidents > 1 ? 's' : ''} declared` : 'No incident declared'} · source{' '}63                {s.vendor_status.url ? (64                  <a href={s.vendor_status.url} rel="noopener nofollow" target="_blank" className="text-accent hover:underline">65                    {s.vendor_status.source}66                  </a>67                ) : (68                  s.vendor_status.source69                )}70              </p>71              {s.vendor_status.titles?.length ? (72                <ul className="list-disc space-y-1 pl-4 text-ink">73                  {s.vendor_status.titles.map((t, i) => (74                    <li key={i}>{t}</li>75                  ))}76                </ul>77              ) : null}78            </div>79          ) : (80            <p className="text-[13px] text-ink-3">No status-page connector for this provider — only our independent observation is shown.</p>81          )}82        </Section>83      </div>8485      <Section label="Affected regions" right={<span>observed from our probes</span>}>86        {s.affected_regions.length ? (87          <ul className="divide-y divide-line">88            {s.affected_regions.map((r) => (89              <li key={r.id} className="flex flex-wrap items-baseline gap-x-4 py-2 text-[13px]">90                <Link href={`/internet/${r.id}`} className="w-48 text-ink hover:text-accent">91                  {r.name}92                </Link>93                <span className="text-ink-2">{r.observation}</span>94              </li>95            ))}96          </ul>97        ) : (98          <p className="py-3 text-[12.5px] text-ink-3">No region shows an anomaly toward this service right now.</p>99        )}100      </Section>101102      <Section label="Probe × target matrix" right={<span>cell = robust z of TTFB vs baseline · red = failing</span>}>103        <ProbeTargetMatrix matrix={s.matrix} targets={s.targets} />104      </Section>105106      <Section label="24 h pressure">107        <ScopePressureChart series={s.history_24h} height={220} />108      </Section>109110      <Section label="Incidents">111        <IncidentsSection incidents={s.incidents} />112      </Section>113114      <Section label="Endpoints">115        <TargetsTable targets={s.targets} />116      </Section>117    </div>118  );119}120